﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Collections.Specialized;
using TrainingReminderSystem.Dal;
using Extentions;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore.Storage;
using TrainingReminderSystem.Model;

namespace TrainingReminderSystem.Bll
{
    /// <summary>
    /// 逻辑层
    /// </summary>
    public partial class SysAccessTokenInfoBll : PcLoginedBll
    {
        #region 添加和编辑的时候 验证数据和设置默认值

        /// <summary>
        /// 添加和编辑的时候 验证数据和设置默认值
        /// </summary>
        /// <param name="db"></param>
        /// <param name="model"></param>
        /// <param name="msg">提示语句</param>
        /// <param name="isAdd">添加还是编辑,可以不管此参数</param>
        /// <returns>是否通过,true表示验证通过,false代表验证没有通过</returns>
        public bool Validate(DbEntities db, SysAccessTokenInfo model, out string msg, bool isAdd)
        {
            msg = string.Empty;
            if (model == null)
            {
                msg = "提交数据出错,请刷新后重试!";
                return false;
            }

            model.CreateDate = DateTime.Now;
            return true;
        }

        #endregion

        #region 分页方法

        /// <summary>
        /// 分页方法
        /// </summary>
        /// <param name="index"></param>
        /// <param name="size"></param>
        /// <param name="form"></param>
        /// <param name="sortField"></param>
        /// <param name="asc"></param>
        /// <returns></returns>
        public AjaxResult<dynamic> GetListByPage(int index, int size, IFormCollection form, string sortField = "ID", bool asc = false)
        {
            using (var db = Db)
            {
                Expression<Func<SysAccessTokenInfo, bool>> where = InitSearch<SysAccessTokenInfo>(form);//拼接查询条件方法

                int counts;
                var tempList = db.SysAccessTokenInfo.ExOrderBy(sortField, asc).ExGetListByPage(index, size, out counts, where).Select(m => m.ID);
                var result = new AjaxResult<dynamic>() { Success = true };
                result.Total = counts;

                IQueryable<SysAccessTokenInfo> list = db.SysAccessTokenInfo.Where(m => tempList.Contains(m.ID))
                    .ExOrderBy(sortField, asc);
                result.Result = list.Select(m => new
                {
                    ID = m.ID,
                    Uid = m.Uid,
                    Pwd = m.Pwd,
                    AccessToken = m.AccessToken,
                    CreateDateTime = m.CreateDateTime,
                    ExpiryDateTime = m.ExpiryDateTime,
                    IpAddress = m.IpAddress,
                    CreateDate = m.CreateDate,
                    Remark = m.Remark
                }).ToList();
                return result;
            }
        }

        #endregion

        #region 得到单对象,返回值有可能为null

        /// <summary>
        /// 得到单对象,返回值有可能为null
        /// </summary>
        /// <param name="id">主键值</param>
        /// <returns></returns>
        public SysAccessTokenInfo GetModel(int id)
        {
            using (var db = Db)
            {
                return db.SysAccessTokenInfo.FirstOrDefault(m => m.ID == id);
            }
        }

        #endregion

        #region 保存数据

        /// <summary>
        /// 保存数据
        /// </summary>
        /// <param name="model">保存的对象,成功之后model对象的ID能得到ID</param>
        /// <returns></returns>
        public AjaxResult<int> Save(SysAccessTokenInfo model)
        {
            using (var db = Db)
            {
                if (model.ID <= 0)
                {
                    return this.Add(model, db);
                }
                return this.Update(model, db);
            }
        }

        #endregion

        #region 添加数据

        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="model">添加的对象,成功之后model对象的ID能得到ID</param>
        /// <returns></returns>
        public AjaxResult<int> Add(SysAccessTokenInfo model)
        {
            using (var db = Db)
            {
                return this.Add(model, db);
            }
        }

        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="model">添加的对象,成功之后model对象的ID能得到ID</param>
        /// <param name="db"></param>
        /// <returns></returns>
        internal AjaxResult<int> Add(SysAccessTokenInfo model, DbEntities db)
        {
            var r = new AjaxResult<int>() { Success = false };
            if (db == null) db = Db;
            string msg;
            if (!Validate(db, model, out msg, true))
            {
                r.Message = msg;
                return r;
            }
            IDbContextTransaction tran = db.Database.CurrentTransaction;
            bool hasTran = tran != null;
            if (hasTran == false) tran = db.Database.BeginTransaction();
            try
            {
                db.SysAccessTokenInfo.Add(model);

                AddLog(db, model, EnumLogType.新建);
                bool isSuccess = db.SaveChanges() >= 0;
                if (hasTran == false)
                {
                    tran.Commit();
                    tran.Dispose();
                    tran = null;
                }
                r.Success = isSuccess;
                r.Message = isSuccess ? "添加成功" : "添加失败,请重试!";
                r.Result = model.ID;
                return r;
            }
            catch (Exception ex)
            {
                ex.ExLogError();
                r.Total = (int)EnumTotal.异常;
                r.Success = false;
                r.Message = "新增失败:" + ex.ExMessageWithInner();
                return r;
            }
            finally
            {
                if (hasTran == false && tran != null) tran.Rollback();
            }
        }

        #endregion

        #region 编辑

        /// <summary>
        /// 编辑
        /// </summary>
        /// <param name="model">添加的对象,成功之后model对象的ID能得到ID</param>
        /// <returns></returns>
        public AjaxResult<int> Update(SysAccessTokenInfo model)
        {
            using (var db = Db)
            {
                return this.Update(model, db);
            }
        }

        /// <summary>
        /// 编辑
        /// </summary>
        /// <param name="model">添加的对象,成功之后model对象的ID能得到ID</param>
        /// <param name="db"></param>
        /// <returns></returns>
        internal AjaxResult<int> Update(SysAccessTokenInfo model, DbEntities db)
        {
            var r = new AjaxResult<int>() { Success = false };
            string msg;
            if (db == null) db = Db;
            if (!Validate(db, model, out msg, false))
            {
                r.Message = msg;
                return r;
            }
            IDbContextTransaction tran = db.Database.CurrentTransaction;
            bool hasTran = tran != null;
            if (hasTran == false) tran = db.Database.BeginTransaction();
            try
            {
                var beforeModel = db.SysAccessTokenInfo.FirstOrDefault(m => m.ID == model.ID);
                if (beforeModel == null)
                {
                    r.Message = LanguageHelper.NoData;
                    return r;
                }
                //beforeModel.ID = model.ID;
                beforeModel.Uid = model.Uid;
                beforeModel.Pwd = model.Pwd;
                beforeModel.AccessToken = model.AccessToken;
                beforeModel.CreateDateTime = model.CreateDateTime;
                beforeModel.ExpiryDateTime = model.ExpiryDateTime;
                beforeModel.IpAddress = model.IpAddress;
                //beforeModel.CreateDate = model.CreateDate;
                beforeModel.Remark = model.Remark;

                AddLog(db, model, EnumLogType.编辑);
                var isSuccess = db.SaveChanges() >= 0;
                if (hasTran == false)
                {
                    tran.Commit();
                    tran.Dispose();
                    tran = null;
                }
                r.Success = isSuccess;
                r.Message = isSuccess ? "编辑成功" : "编辑失败,请重试!";
                r.Result = model.ID;
                return r;
            }
            catch (Exception ex)
            {
                ex.ExLogError();
                r.Success = false;
                r.Message = "编辑失败:" + ex.ExMessageWithInner();
                return r;
            }
            finally
            {
                if (hasTran == false && tran != null) tran.Rollback();
            }
        }

        #endregion

        #region 删除

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public AjaxResult<int> Del(int id)
        {
            using (var db = Db)
            {
                return Del(id, db);
            }
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        internal AjaxResult<int> Del(int id, DbEntities db)
        {
            var r = new AjaxResult<int>() { Success = false };
            if (db == null) db = Db;
            IDbContextTransaction tran = db.Database.CurrentTransaction;
            bool hasTran = tran != null;
            if (hasTran == false) tran = db.Database.BeginTransaction();
            try
            {
                var beforeModel = db.SysAccessTokenInfo.FirstOrDefault(m => m.ID == id);
                if (beforeModel == null)
                {
                    r.Message = LanguageHelper.NoData;
                    return r;
                }
                beforeModel.IsDel = true; //db.SysAccessTokenInfo.Remove(beforeModel);

                AddLog(db, beforeModel, EnumLogType.删除);
                var isSuccess = db.SaveChanges() >= 0;
                if (hasTran == false)
                {
                    tran.Commit();
                    tran.Dispose();
                    tran = null;
                }
                r.Success = isSuccess;
                r.Message = isSuccess ? "删除成功" : "删除失败,请重试!";
                return r;
            }
            catch (Exception ex)
            {
                ex.ExLogError();
                r.Success = false;
                r.Message = "删除失败:" + ex.ExMessageWithInner();
                return r;
            }
            finally
            {
                if (hasTran == false && tran != null) tran.Rollback();
            }
        }

        #endregion

        #region 创建AccessTokenModel

        #region 辅助类

        /// <summary>
        /// 授权token对象
        /// 到期时间过半,请求才会刷新AccessToken
        /// </summary>
        public class AccessTokenModel
        {
            /// <summary>
            /// 授权token
            /// </summary>
            public string AccessToken { get; set; }

            /// <summary>
            /// 到期时间
            /// </summary>
            public DateTime ExpiryDateTime { get; set; }

            /// <summary>
            /// AccessToken生成时间
            /// </summary>
            public DateTime CreateDateTime { get; set; }
        }

        /// <summary>
        /// 获取token,返回值为AccessTokenModel;到期时间过半,请求才会刷新AccessToken
        /// </summary>
        public class TokenModelSubmit
        {
            /// <summary>
            /// 帐号
            /// </summary>
            public string Uid { get; set; }

            /// <summary>
            /// 密码
            /// </summary>
            public string Pwd { get; set; }
        }

        #endregion

        /// <summary>
        /// 有效期时间 20MIN
        /// </summary>
        public const int ValidateMin = 20;

        /// <summary>
        /// 通过帐号密码创建AccessToken
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        public AjaxResult<AccessTokenModel> GetTokenModel(TokenModelSubmit post)
        {
            var r = new AjaxResult<AccessTokenModel>();
            if (post == null)
            {
                r.Message = "参数错误,未获取到Uid和Pwd";
                return r;
            }

            if (string.IsNullOrEmpty(post.Uid) || string.IsNullOrEmpty(post.Pwd))
            {
                r.Message = "参数错误,未获取到Uid和Pwd!";
                return r;
            }

            using (var db = Db)
            {
                var model = db.SysAccessTokenInfo.FirstOrDefault(m => m.Uid == post.Uid && m.Pwd == post.Pwd);
                if (model == null)
                {
                    r.Message = "帐号或密码错误";
                    return r;
                }

                //没有创建过,或过期时间超过了
                if (model.CreateDateTime == null || model.ExpiryDateTime == null ||
                    string.IsNullOrEmpty(model.AccessToken) ||
                    (model.CreateDateTime.Value.AddMinutes(ValidateMin / 2) < DateTime.Now) || (model.ExpiryDateTime.Value < DateTime.Now))
                {
                    if (!string.IsNullOrEmpty(model.AccessToken))
                    {
                        CacheHelper.RemoveCache(model.AccessToken);
                    }

                    model.CreateDateTime = DateTime.Now;
                    model.ExpiryDateTime = model.CreateDateTime.Value.AddMinutes(ValidateMin);
                    model.AccessToken = Guid.NewGuid().ToString().Replace("-", string.Empty).ExTrim();
                    db.SaveChanges();
                    //直接创建,然后返回
                    r.Result = BuildSysAccessTokenInfo(model);
                    r.Success = true;
                    return r;
                }

                //直接返回对象
                r.Result = BuildSysAccessTokenInfo(model);
                r.Success = true;
                return r;
            }
        }

        private AccessTokenModel BuildSysAccessTokenInfo(SysAccessTokenInfo model)
        {
            var result = new AccessTokenModel();
            result.AccessToken = model.AccessToken;
            result.CreateDateTime = model.CreateDateTime.Value;
            result.ExpiryDateTime = model.ExpiryDateTime.Value;
            CacheHelper.SetAbsoluteCache(model.AccessToken, result,
                Convert.ToInt32((model.ExpiryDateTime.Value - model.CreateDateTime.Value).TotalSeconds));
            return result;
        }

        /// <summary>
        /// 验证AccessToken
        /// </summary>
        /// <param name="accessToken"></param>
        /// <returns></returns>
        public AjaxResult<int> ValidateAccessToken(string accessToken)
        {
            if (string.IsNullOrEmpty(accessToken))
            {
                return AjaxResult<int>.ErrorResult("提交参数错误,未获取到AccessToken");
            }

            accessToken = accessToken.ExTrim();
            var accessTokenModel = CacheHelper.GetCache(accessToken) as AccessTokenModel;
            if (accessTokenModel == null)
            {
                //数据库查询一次
                using var db = DbNoFilter;
                var model = db.SysAccessTokenInfo.FirstOrDefault(m => m.AccessToken == accessToken);
                if (model == null)
                {
                    return AjaxResult<int>.ErrorResult("该AccessToken无效,请重新获取AccessToken");
                }

                accessTokenModel = BuildSysAccessTokenInfo(model);
            }

            if ((accessTokenModel.CreateDateTime.AddMinutes(ValidateMin) < DateTime.Now) || accessTokenModel.ExpiryDateTime < DateTime.Now)
            {
                return AjaxResult<int>.ErrorResult("AccessToken已过期,请重新获取新的AccessToken");
            }

            return AjaxResult<int>.SuccessResult(1);
        }

        #endregion
    }
}
